package ru.sushka.lunch.dao.files;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

import ru.sushka.lunch.dao.AbstractDao;
import ru.sushka.lunch.enitiy.Persistentce;

public abstract class FileDao<T extends Persistentce> implements AbstractDao<T> {

    protected abstract String getFileName();

    protected abstract String convertToCsv(T persistent);

    protected abstract T parseCsv(String csvline) throws ParseException;

    @Override
    public T get(int id) {
        List<T> TList = getList("");
        if (id <= TList.size()) {
            return (T) TList.get(id-1);
        }
        throw new RuntimeException("");
    }

    @Override
    /**
     * для текстовых файлов фильтр не используется
     */
    public List<T> getList(String filter) {
        List<T> TList = new ArrayList<T>();
        List<String> stringList = loadFromFile(getFileName());
        int id = 1;
        for (String line : stringList) {
            try {
                T persistent = parseCsv(line);
                persistent.setId(id);
                id++;
                TList.add(persistent);
            } catch (ParseException e) {
                continue;//не можем отпарсить строку - парсим следующую
            }
        }
        return TList;
    }
    
    public int getCount(){
        return getCountLines(getFileName());
    }
    
    @Override
    public void insert(T persistent) {
        addToFile(getFileName(), convertToCsv(persistent));
        int id = getCountLines(getFileName());
        persistent.setId(id++);
    }

    @Override
    public void delete(T persistent) {
        List<String> stringList = loadFromFile(getFileName());
        stringList.remove(persistent.getId() - 1);
        saveToFile(getFileName(), stringList);
    }

    @Override
    public void update(T persistent) {
        if (persistent.getId() != 0) {
            List<String> stringList = loadFromFile(getFileName());
            stringList.set(persistent.getId() - 1, convertToCsv(persistent));
            saveToFile(getFileName(), stringList);
        } else {
            insert(persistent);
        }
    }

    protected List<String> loadFromFile(String fileName) {
        List<String> stringList = new ArrayList<String>();
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new InputStreamReader(
                    new FileInputStream(fileName), "UTF-8"));
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                stringList.add(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bufferedReader != null)
                    bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return stringList;
    }

    protected int getCountLines(String fileName) {
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new InputStreamReader(
                    new FileInputStream(fileName), "UTF-8"));
            int count = 0;
            while ((bufferedReader.readLine()) != null) {
                count++;
            }
            bufferedReader.close();
            return count;
        } catch (IOException e) {
            e.printStackTrace();
            return 0;
        } finally {
            try {
                if (bufferedReader != null)
                    bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    // добавляет строку в конец файла
    protected void addToFile(String fileName, String line) {
        PrintStream printStream = null;
        try {
            printStream = new PrintStream(new FileOutputStream(fileName, true),
                    true);
            printStream.println(line);
            printStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (printStream != null)
                printStream.close();
        }
    }

    // перезаписывает файл
    protected void saveToFile(String fileName, List<String> stringList) {
        PrintStream printStream = null;
        try {
            printStream = new PrintStream(new FileOutputStream(fileName), true);
            for (String line : stringList) {
                printStream.println(line);
            }
            printStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (printStream != null)
                printStream.close();
        }
    }
}